package com.gitee.wsl.mathematics.geometry.d2.ray

import com.gitee.wsl.mathematics.geometry.d2.line.Line
import com.gitee.wsl.mathematics.vector.ext.Vec2f
import com.gitee.wsl.mathematics.vector.ext.angle
import com.gitee.wsl.mathematics.vector.vec2.Vec2f
import com.gitee.wsl.unit.angle.AngleUnit

/** Represents an infinite [Ray] starting at [point] in the specified [direction] with an [angle] */
/** Constructs a [Ray] starting from [point] in the specified [direction] */
data class Ray2D(
    /** Starting point */
    val point: Vec2f,
     /** Normalized direction of the ray starting at [point] */
    val direction: Vec2f,
)  {
    companion object {
     /** Creates a ray starting in [start] and passing by [end] */
        fun fromTwoPoints(start: Vec2f, end: Vec2f) = Ray2D(start, end - start, Unit)
    }

    //val point: Point get() = Point(data.f0, data.f1)
    //val direction: Vector2 get() = Vector2(data.f2, data.f3)

   /** Angle between two points */
    val angle: AngleUnit get() = direction.angle

    /** Constructs a [Ray] starting from [point] in the specified [direction] */
    constructor(point: Vec2f, direction: Vec2f, unit: Unit = Unit) : this(point, direction.normalized)

    /** Constructs a [Ray] starting from [point] in the specified [angle] */
    constructor(point: Vec2f, angle: AngleUnit) : this(point, Vec2f(angle), Unit)

    //private constructor(point: Point, normalizedDirection: Vector2, unit: Unit) : this(point.x, point.y, normalizedDirection.x, normalizedDirection.y)

/** Checks if [this] and [other]are equals with an [epsilon] difference */

   //fun isAlmostEquals(other: Ray, epsilon: Double): Boolean = this.point.isAlmostEquals(other.point, epsilon) && this.direction.isAlmostEquals(other.direction, epsilon)

/** Checks if [this] and [other]are equals with an [epsilon] tolerance */

    //fun transformed(m: Matrix): Ray = Ray(m.transform(point), m.deltaTransform(direction).normalized)

/** Converts this [Ray] into a [Line] of a specific [length] starting by [point] */

    fun toLine(length: Double = 100000.0): Line = Line(point, point + direction * length)

    override fun toString(): String = "Ray($point, $angle)"
}
